import socket,select
import struct,uuid
from helpFunc import *

askConn_g = 1
connBack_g = 2
full_g = 3
notfull_g = 4
data_g = 5
close_g = 6

class tcpReBase():
    def __init__(self):
        self.connSock = None
        self.proxySocks = {}
        self.idMap = {}
        self.readCache = b''    
        self.connNum = 0
        self.maxNum = 990
        self.cachePerConn = 300*1024
        self.peerBuf = b''
        self.peerBufMax = tcp_maxBuffSize
        self.decodeId = b''
        self.decodeType = -1;
        self.decodeData = b''
        
    def decodeMsg(self,msg):
        self.decodeType=msg[0]
        self.decodeId=msg[1:17]
        self.decodeData = msg[17:]
                
    def getReadSocks(self):        
        rl = []
        for k in self.proxySocks:
            v = self.proxySocks[k]
            if not v['peerFull'] and not v['peerclose']:
                rl.append(k)
        return rl
    
    def sendMsg(self,msg):
        self.peerBuf+=msg
        
    def getWriteSocks(self):
        wl = []
        for one in self.proxySocks:
            if self.proxySocks[one]['data']:
                wl.append(one)  
        return wl
        
    def dealData(self,sock,data):
        st = self.readCache + data
        msgList = []

        while True:
            if len(st)<4:
                break 
            ll = struct.unpack('i',st[:4])[0]
            if len(st)<ll:
                break 
            msg = st[4:ll]
            st = st[ll:]
            msgList.append(msg)
        self.readCache  = st
        return msgList
    
    def makeMsg(self,ty,id,data):
        msg = struct.pack('B',ty)+id+data
        return struct.pack('i',len(msg)+4)+msg
    
    def dealConnsockNormal(self,id,ty,d):        
        if id not in self.idMap:
            return                
        sock = self.idMap[id]['sock']
        if ty==full_g:
            self.proxySocks[sock]['peerFull'] = True
        if ty==notfull_g:
            self.proxySocks[sock]['peerFull'] = False                
        if ty==data_g:
            self.proxySocks[sock]['data']+=d
            if len(self.proxySocks[sock]['data'])>self.cachePerConn and not self.proxySocks[sock]['tellMyFull']:
                self.proxySocks[sock]['tellMyFull'] = True
                msg = self.makeMsg(full_g,id,b'0')               
                self.sendMsg(msg) 
                
        if ty==close_g:
            self.proxySocks[sock]['peerclose'] = True    
            if not self.proxySocks[sock]['data']:
                sock.close()
                self.connNum -=1                             
                del self.proxySocks[sock]
                del self.idMap[id]  
                print ('conn close',self.connNum )
                            
    def dealProxysocks(self,sock):   
        try:
            ss = sock.recv(con_recLen)
        except Exception as e:
            print (e)
            ss = b''                
        if sock not in self.proxySocks:
            return
        id = self.proxySocks[sock]['id']
        if not ss:
            sock.close()
            del self.proxySocks[sock]
            del self.idMap[id]
            self.connNum -=1                             
            print ('conn close',self.connNum)
            msg = self.makeMsg(close_g,id,b'0')               
            self.sendMsg(msg)         
            return
        msg = self.makeMsg(data_g,id,ss)               
        self.sendMsg(msg)
        
                  
                
    def dealWritesocks(self,sock):                
        if sock not in self.proxySocks:
            return            
        try:
            n = sock.send(self.proxySocks[sock]['data'])
            self.proxySocks[sock]['data'] = self.proxySocks[sock]['data'][n:]
        
            if len(self.proxySocks[sock]['data']) <= self.cachePerConn and  self.proxySocks[sock]['tellMyFull']:
                self.proxySocks[sock]['tellMyFull'] = False
                id = self.proxySocks[sock]['id']
                dd = self.makeMsg(notfull_g,id,b'0')              
                self.sendMsg(dd)      
                
            if (not self.proxySocks[sock]['data']) and self.proxySocks[sock]['peerclose']:
                sock.close()
                id = self.proxySocks[sock]['id']
                del self.proxySocks[sock]
                del self.idMap[id]                    
                self.connNum -=1                             
                print ('conn close',self.connNum)
        except Exception as e:
            print (e)
            sock.close()
            self.connNum -=1                             
            id = self.proxySocks[sock]['id']
            dd = self.makeMsg(close_g,id,b'0')     
            self.sendMsg(dd)  
            del self.proxySocks[sock]
            del self.idMap[id]
            print ('conn close',self.connNum)
